package com.woniuxy.util;

import com.woniuxy.entity.po.operations.BindCostAndTypeRules;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class TimeRuleValidatorUtil {

	private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");

	/**
	 * 主校验方法
	 */
	public static void validateTimeRules(List<BindCostAndTypeRules> rules) {
		// 1. 基础校验
		checkTimeFormat(rules);
		checkTimeOrder(rules);

		// 2. 排序时间段（按开始时间）
		List<BindCostAndTypeRules> sortedRules = sortRules(rules);

		// 3. 覆盖性校验
		checkFullCoverage(sortedRules);

		// 4. 无交叉校验
		checkNoOverlap(sortedRules);
	}

	// 校验时间格式是否正确
	private static void checkTimeFormat(List<BindCostAndTypeRules> rules) {
		for (BindCostAndTypeRules rule : rules) {
			if (!isValidTime(rule.getStartTime())) {
				throw new IllegalArgumentException("Invalid startTime: " + rule.getStartTime());
			}
			if (!isValidTime(rule.getEndTime())) {
				throw new IllegalArgumentException("Invalid endTime: " + rule.getEndTime());
			}
		}
	}

	// 校验单个时间格式
	private static boolean isValidTime(String time) {
		try {
			LocalTime.parse(time, TIME_FORMATTER);
			return true;
		} catch (DateTimeParseException e) {
			return false;
		}
	}

	// 校验时间段顺序（确保 endTime > startTime）
	private static void checkTimeOrder(List<BindCostAndTypeRules> rules) {
		for (BindCostAndTypeRules rule : rules) {
			LocalTime start = parseTime(rule.getStartTime());
			LocalTime end = parseTime(rule.getEndTime());
			if (!end.isAfter(start)) {
				throw new IllegalArgumentException("endTime必须大于startTime（规则ID：" + rule.getId() + ")");
			}
		}
	}

	// 按开始时间排序
	public static List<BindCostAndTypeRules> sortRules(List<BindCostAndTypeRules> rules) {
		List<BindCostAndTypeRules> sorted = new ArrayList<>(rules);
		sorted.sort(Comparator.comparing(rule -> LocalTime.parse(rule.getStartTime(), TIME_FORMATTER)));
		return sorted;
	}

	// 检查是否覆盖完整24小时
	private static void checkFullCoverage(List<BindCostAndTypeRules> sortedRules) {
		// 检查第一个时间段以00:00开始
		if (!"00:00".equals(sortedRules.get(0).getStartTime())) {
			throw new IllegalArgumentException("第一个时间段必须从00:00开始");
		}

		// 检查最后一个时间段以24:00结束（原始字符串）
		BindCostAndTypeRules lastRule = sortedRules.get(sortedRules.size() - 1);
		if (!"24:00".equals(lastRule.getEndTime())) {
			throw new IllegalArgumentException("最后一个时间段必须结束于24:00");
		}

		// 检查时间连续性
		LocalTime previousEnd = parseTime(sortedRules.get(0).getEndTime());
		for (int i = 1; i < sortedRules.size(); i++) {
			LocalTime currentStart = parseTime(sortedRules.get(i).getStartTime());

			// 特殊处理跨午夜情况（24:00与00:00衔接）
			if (previousEnd.equals(LocalTime.MAX) && currentStart.equals(LocalTime.MIN)) {
				previousEnd = parseTime(sortedRules.get(i).getEndTime());
				continue;
			}

			if (!currentStart.equals(previousEnd)) {
				throw new IllegalArgumentException("时间段不连续（规则ID："
						+ sortedRules.get(i-1).getId() + " 和 " + sortedRules.get(i).getId() + ")");
			}

			previousEnd = parseTime(sortedRules.get(i).getEndTime());
		}
	}

	// 检查时间段是否有重叠
	private static void checkNoOverlap(List<BindCostAndTypeRules> sortedRules) {
		LocalTime previousEnd = LocalTime.parse(sortedRules.get(0).getEndTime(), TIME_FORMATTER);
		for (int i = 1; i < sortedRules.size(); i++) {
			LocalTime currentStart = LocalTime.parse(sortedRules.get(i).getStartTime(), TIME_FORMATTER);
			if (currentStart.isBefore(previousEnd)) {
				throw new IllegalArgumentException("Overlap between rules: " + sortedRules.get(i-1).getId() + " and " + sortedRules.get(i).getId());
			}
			previousEnd = LocalTime.parse(sortedRules.get(i).getEndTime(), TIME_FORMATTER);
		}
	}

	private static LocalTime parseTime(String time) {
		if ("24:00".equals(time)) {
			return LocalTime.MAX; // 24:00 转换为 23:59:59.999999999
		}
		try {
			return LocalTime.parse(time, TIME_FORMATTER);
		} catch (DateTimeParseException e) {
			throw new IllegalArgumentException("Invalid time format: " + time);
		}
	}
}